package org.vison.wonfu.framework.codestyle;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import org.apache.commons.cli.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.vison.wonfu.framework.codestyle.config.CheckerConfig;
import org.vison.wonfu.framework.codestyle.core.CheckerFramework;
import org.vison.wonfu.framework.codestyle.core.Printer;
import org.vison.wonfu.framework.codestyle.issue.Issue;

import java.io.File;
import java.io.IOException;
import java.util.Collection;

/**
 * 程序入口类
 */
public class CodeStyle {

    private static final String ANSI_RESET = "\u001B[0m";
    private static final String ANSI_RED = "\u001B[31m";
    private static final String ANSI_YELLOW = "\u001B[33m";
    private static final String ANSI_GREEN = "\u001B[32m";
    private static final String ANSI_CYAN = "\u001B[36m";
    private static final String ANSI_BOLD = "\u001B[1m";
    private static final String EMOJ_SEARCH = "\uD83D\uDD0D";
    private static final String EMOJ_OK = "✅";
    private static final String EMOJ_WARNING = "\u26A0";
    private static final String EMOJ_DATA = "\uD83D\uDCBE";

    private static Printer printer;
    private static int totalIssues = 0;


    public static void main(String[] args) {
        Options options = new Options();
        options.addOption("v", "verbose", false, "输出详细检查报告");
        options.addOption("c", "config", true, "指定配置文件路径");
        options.addOption("h", "help", false, "显示帮助信息");
        CommandLineParser parser = new DefaultParser();
        try {
            CommandLine cmd = parser.parse(options, args);

            if (cmd.hasOption("h")) {
                printHelp(options);
                System.exit(0);
            }
            boolean verbose = cmd.hasOption("v");
            Printer printer = new Printer(verbose);
            String[] remainingArgs = cmd.getArgs();
            if (remainingArgs.length == 0) {
                System.err.println("请指定要检查的目录");
                printHelp(options);
                System.exit(1);
            }
            String targetDirectory = remainingArgs[0];
            String configPath = cmd.getOptionValue("c", "checker-config.yml");
            run(configPath, targetDirectory,printer);
            if(totalIssues > 0) {
                System.exit(1);
            } else {
                System.exit(0);
            }
        }catch (ParseException e) {
            System.err.println("解析命令行参数失败: " + e.getMessage());
            System.exit(1);
        }catch (Exception e) {
            System.err.println("检查过程中发生错误: " + e.getMessage());
            System.exit(1);
        }
    }

    public static void run(String configPath, String targetDirectory,Printer printer) {
        try {
            // 加载配置
            CheckerConfig config = loadConfig(configPath);

            // 初始化检查框架
            CheckerFramework framework = new CheckerFramework(config);
            printer.print(EMOJ_OK+" 已加载 " + framework.getLoadedRulesCount() + " 个检查规则");

            // 获取所有Java文件
            Collection<File> javaFiles = getJavaFiles(targetDirectory);
            printer.print(EMOJ_DATA+" 发现 " + javaFiles.size() + " 个Java文件需要检查");

            // 检查每个文件
            for (File file : javaFiles) {
                try {
                    CompilationUnit cu = StaticJavaParser.parse(file);
                    framework.checkFile(file, cu);
                } catch (Exception e) {
                    System.err.println("解析文件 " + file.getAbsolutePath() + " 时出错: " + e.getMessage());
                }
            }
            // 输出检查结果
            printReport(framework,printer);
            totalIssues = (int) framework.getIssueCollector().getAllIssues().stream()
                    .filter(issue -> Issue.Severity.ERROR.equals(issue.getSeverity()))
                    .count();
        } catch (Exception e) {
            System.err.println("检查过程中发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 加载配置文件
    private static CheckerConfig loadConfig(String configPath) throws IOException {
        File configFile = new File(configPath);
        if (configFile.exists() && configFile.isFile()) {
            System.out.println(EMOJ_SEARCH+" 加载配置文件: " + configFile.getAbsolutePath());
            return CheckerConfig.loadFromFile(configPath);
        } else {
            System.out.println("配置文件 " + configPath + " 不存在，使用默认配置");
            return new CheckerConfig();
        }
    }
    
    // 获取目录下所有Java文件
    private static Collection<File> getJavaFiles(String directoryPath) {
        File directory = new File(directoryPath);
        if (!directory.exists() || !directory.isDirectory()) {
            throw new IllegalArgumentException("无效的目录路径: " + directoryPath);
        }
        
        return FileUtils.listFiles(
            directory,
            new WildcardFileFilter("*.java"),
            TrueFileFilter.INSTANCE
        );
    }

    private static void printHelp(Options options) {
        HelpFormatter formatter = new HelpFormatter();
        String header = "Do something useful with an input file";
        String footer = "Please report issues at https://example.com/issues";

        formatter.printHelp("java -jar code-checker.jar [选项] <检查目录>",header, options,footer,true);
    }
    
    // 打印检查报告
    private static void printReport(CheckerFramework framework,Printer printer) {
        printer.print("\n" + ANSI_BOLD + ANSI_CYAN + "===== 📋 代码检查报告 =====" + ANSI_RESET);
        printer.print(ANSI_BOLD + "总文件数: " + framework.getIssueCollector().getAllIssues().stream()
                .map(issue -> issue.getFile().getAbsolutePath())
                .distinct()
                .count());
        printer.print(ANSI_BOLD + "总问题数: " + framework.getIssueCollector().getTotalIssueCount());
        printer.print("  错误: " + framework.getIssueCollector().getIssueCountBySeverity(Issue.Severity.ERROR)+" ❌");
        printer.print("  警告: " + framework.getIssueCollector().getIssueCountBySeverity(Issue.Severity.WARNING)+ " ⚠️");
        printer.print("  信息: " + framework.getIssueCollector().getIssueCountBySeverity(Issue.Severity.INFO)+ " ℹ️");
        printer.print("\n详细问题:");
        for (Issue issue : framework.getIssueCollector().getAllIssues()) {
            printer.print(issue);
        }
    }
}
